package com.drg.center.dao;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.drg.center.entity.PatientCaseEsPO;
import com.drg.center.entity.result.*;
import com.drg.center.utils.BusinessDateUtil;
import com.drg.center.utils.EsResultResolveUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.guaike.core.entity.exception.ApiException;
import com.guaike.core.utils.BigDecimalUtil;
import com.guaike.core.utils.CompareUtil;
import com.guaike.core.utils.LocalDateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.BucketOrder;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;

/**
 * @Author: zhangxilin
 * @Date: 2025/1/7
 */
@Slf4j
@Repository
public class EsDataMiningExtDAO {


    @Autowired
    private ElasticsearchOperations elasticsearchOperations;

    /**
     * 医保标杆值分析(DSL-115)
     *
     * @param searchDrgCode
     * @param startDate
     * @param endDate
     */
    public List<MedicareBenchmarkingAnalysisPageVO> benchmarkStt(String searchDrgCode, LocalDate startDate, LocalDate endDate) {

        // 检索条件
        BoolQueryBuilder queryBuilder = boolQuery();
        queryBuilder.must(QueryBuilders.termQuery("hasOut", true));
        if (StringUtils.isNotBlank(searchDrgCode)) {
            queryBuilder.must(QueryBuilders.termQuery("drgCode", searchDrgCode));
        }
        if (startDate != null) {
            queryBuilder.must(QueryBuilders.rangeQuery("outHospitalDate").gte(LocalDateUtil.getTimestamp(startDate)));
        }
        if (endDate != null) {
            queryBuilder.must(QueryBuilders.rangeQuery("outHospitalDate").lt(LocalDateUtil.getTimestamp(endDate.plusDays(1))));
        }

        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .addAggregation(AggregationBuilders.terms("drgAgg")
                        .field("drgCode")
                        .size(10000)
                        .order(BucketOrder.aggregation("totalCost", false))
                        .subAggregation(AggregationBuilders.sum("totalCost").field("totalCost").format("0.00"))
                        .subAggregation(AggregationBuilders.avg("avgCost").field("totalCost").format("0.00"))
                        .subAggregation(AggregationBuilders.count("caseCount").field("caseCode"))
                        .subAggregation(AggregationBuilders.avg("avg_medicine_cost").field("medicineCost").format("0.00"))
                        .subAggregation(AggregationBuilders.avg("avg_inpatientDays").field("inpatientDays").format("0.00"))
                        .subAggregation(AggregationBuilders.topHits("drgName").size(1)
                                .fetchSource(new String[]{"drgName"}, null))
                )
                .withPageable(PageRequest.of(0, 1))
                .build();

        Aggregations aggregations = elasticsearchOperations.search(searchQuery, PatientCaseEsPO.class).getAggregations();
        Terms deptAgg = (ParsedStringTerms) aggregations.get("drgAgg");
        List<MedicareBenchmarkingAnalysisPageVO> list = new ArrayList<>();
        for (Terms.Bucket bucket : deptAgg.getBuckets()) {
            MedicareBenchmarkingAnalysisPageVO vo = new MedicareBenchmarkingAnalysisPageVO();
            //DRG名称
            TopHits drgNameHits = (TopHits) bucket.getAggregations().get("drgName");
            String drgName = EsResultResolveUtil.getName(drgNameHits, 0, "drgName");


            //医疗总费用
            ParsedSum totalCostSum = bucket.getAggregations().get("totalCost");
            BigDecimal totalCost = BigDecimalUtil.parseBigDecimal(totalCostSum.getValueAsString());

            //入组病例数
            ValueCount caseCountValueCount = bucket.getAggregations().get("caseCount");
            Integer caseCount = (int) caseCountValueCount.getValue();

            //本院次均费用
            ParsedAvg avgCostParsed = bucket.getAggregations().get("avgCost");
            BigDecimal avgCost = BigDecimalUtil.parseBigDecimal(avgCostParsed.getValueAsString());

            //本院次均药品费用
            ParsedAvg avgMedicineCostParsed = bucket.getAggregations().get("avg_medicine_cost");
            BigDecimal avgMedicineCost = BigDecimalUtil.parseBigDecimal(avgMedicineCostParsed.getValueAsString());

            //本院平均住院日
            ParsedAvg avgInpatientDaysParsed = bucket.getAggregations().get("avg_inpatientDays");
            BigDecimal avgInpatientDays = BigDecimalUtil.parseBigDecimal(avgInpatientDaysParsed.getValueAsString());
            vo.setChsDrgName(drgName);
            vo.setInDrgCaseCount(caseCount);
            vo.setHospitalAvgCostParsed(avgCost);
            vo.setHospitalAvgMedicineCostParsed(avgMedicineCost);
            vo.setHospitalAvgDays(avgInpatientDays);
            vo.setHospitalCmi(randomRate(70, 110).toPlainString());
            vo.setHospitalTotalWeight(randomRate(10, 50).toPlainString());
            list.add(vo);
        }
        return list;
    }

    /**
     * 患者结构分析(DSL-116)
     *
     * @param startDate
     * @param endDate
     * @param startAge
     * @param endAge
     * @param insuranceType
     */
    public PatientStructuralAnalysisEsVO structuralStt(LocalDate startDate, LocalDate endDate, Integer startAge, Integer endAge, String insuranceType) {
        // 检索条件
        BoolQueryBuilder queryBuilder = boolQuery();
        queryBuilder.must(QueryBuilders.termQuery("hasOut", true));
        if (StringUtils.isNotBlank(insuranceType)) {
            queryBuilder.must(QueryBuilders.nestedQuery("personInfoVO", QueryBuilders.termQuery("personInfoVO.medicareType", insuranceType), ScoreMode.None));
        }
        if (startDate != null) {
            queryBuilder.must(QueryBuilders.rangeQuery("settleDate").gte(LocalDateUtil.getTimestamp(startDate)));
        }
        if (endDate != null) {
            queryBuilder.must(QueryBuilders.rangeQuery("settleDate").lt(LocalDateUtil.getTimestamp(endDate.plusDays(1))));
        }
        if (startAge != null) {
            queryBuilder.must(QueryBuilders.nestedQuery("personInfoVO", QueryBuilders.rangeQuery("personInfoVO.patientAge").gte(startAge), ScoreMode.None));
        }
        if (endAge != null) {
            queryBuilder.must(QueryBuilders.nestedQuery("personInfoVO", QueryBuilders.rangeQuery("personInfoVO.patientAge").lt(endAge), ScoreMode.None));
        }

        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .withPageable(PageRequest.of(0, 1))
                .addAggregation(AggregationBuilders.count("caseCount").field("caseCode"))
                .addAggregation(AggregationBuilders.cardinality("drgCount").field("drgCode"))
                .addAggregation(AggregationBuilders.sum("totalCost").field("totalCost").format("0.00"))
                .addAggregation(AggregationBuilders.sum("medicine_cost").field("medicineCost").format("0.00"))
                .addAggregation(AggregationBuilders.sum("consumables_cost").field("consumablesCost").format("0.00"))
                .addAggregation(AggregationBuilders.sum("other_cost").field("otherCost").format("0.00"))
                .addAggregation(AggregationBuilders.avg("avgCost").field("totalCost").format("0.00"))
                .addAggregation(AggregationBuilders.avg("avg_medicine_cost").field("medicineCost").format("0.00"))
                .addAggregation(AggregationBuilders.avg("avg_consumables_cost").field("consumablesCost").format("0.00"))
                .addAggregation(AggregationBuilders.avg("avg_other_cost").field("otherCost").format("0.00"))
                .build();

        Aggregations aggregations = elasticsearchOperations.search(searchQuery, PatientCaseEsPO.class).getAggregations();

        //病例数
        ValueCount caseCountValueCount = aggregations.get("caseCount");
        Integer caseCount = (int) caseCountValueCount.getValue();

        //病组数
        Cardinality drgCountCardinality = aggregations.get("drgCount");
        int drgCount = (int) drgCountCardinality.getValue();

        //医疗总费用
        Sum totalCostSum = aggregations.get("totalCost");
        BigDecimal totalCost = BigDecimalUtil.parseBigDecimal(totalCostSum.getValueAsString());

        //次均费用
        Avg totalCostAvg = aggregations.get("avgCost");
        BigDecimal avgCost = BigDecimalUtil.parseBigDecimal(totalCostAvg.getValueAsString().equals("Infinity") ? "0.00" : totalCostAvg.getValueAsString());

        //药品费用
        Sum medicineCostSum = aggregations.get("medicine_cost");
        BigDecimal medicineCost = BigDecimalUtil.parseBigDecimal(medicineCostSum.getValueAsString());

        //次均药品费用
        Avg medicineCostAvg = aggregations.get("avg_medicine_cost");
        BigDecimal avgMedicineCost = BigDecimalUtil.parseBigDecimal(medicineCostAvg.getValueAsString().equals("Infinity") ? "0.00" : medicineCostAvg.getValueAsString());

        //耗材费用
        Sum consumablesCostSum = aggregations.get("consumables_cost");
        BigDecimal ConsumablesCost = BigDecimalUtil.parseBigDecimal(consumablesCostSum.getValueAsString());

        //次均耗材费用
        Avg consumablesCostAvg = aggregations.get("avg_consumables_cost");
        BigDecimal avgConsumablesCost = BigDecimalUtil.parseBigDecimal(consumablesCostAvg.getValueAsString().equals("Infinity") ? "0.00" : consumablesCostAvg.getValueAsString());

        //其他费用
        Sum otherCostSum = aggregations.get("other_cost");
        BigDecimal otherCost = BigDecimalUtil.parseBigDecimal(otherCostSum.getValueAsString());

        //次均其他费用
        Avg otherCostAvg = aggregations.get("avg_other_cost");
        String avgOtherCostStr = otherCostAvg.getValueAsString();
        if (CompareUtil.isEqual("Infinity", avgOtherCostStr)) {
            avgOtherCostStr = "0.00";
        }
        BigDecimal avgOtherCost = BigDecimalUtil.parseBigDecimal(avgOtherCostStr);
        PatientStructuralAnalysisEsVO vo = new PatientStructuralAnalysisEsVO();
        vo.setCaseCount(caseCount);
        vo.setDiseaseGroup(drgCount);
        vo.setTotalTreatCost(totalCost);
        vo.setAvgCost(avgCost);
        vo.setMedicineCost(medicineCost);
        vo.setMedicineAvgCost(avgMedicineCost);
        vo.setConsumablesCost(ConsumablesCost);
        vo.setConsumablesAvgCost(avgConsumablesCost);
        vo.setOtherCost(otherCost);
        vo.setOtherAvgCost(avgOtherCost);
        return vo;
    }

    /**
     * 基金预算使用分析(DSL-117)
     *
     * @param year
     * @param departCodeList
     * @return
     */
    public ChartLineVO getExpireFundCostTrend(Integer year, List<String> departCodeList) {

        if (year == null) {
            throw new ApiException("请选择年份");
        }

        List<String> dataX = BusinessDateUtil.getMonthList(year);

        // 检索条件
        BoolQueryBuilder queryBuilder = boolQuery();
        queryBuilder.must(QueryBuilders.termQuery("hasOut", true));

        if (!CollectionUtils.isEmpty(departCodeList)) {
            queryBuilder.must(QueryBuilders.termsQuery("outDepartCode", departCodeList));
        }


        LocalDateTime firstDayOfYear = LocalDateUtil.getFirstDayOfYear(year);
        LocalDateTime lastDayOfYear = LocalDateUtil.getLastDayOfYear(year);
        queryBuilder.must(QueryBuilders.rangeQuery("outHospitalDate").gte(LocalDateUtil.getTimestamp(firstDayOfYear)));
        queryBuilder.must(QueryBuilders.rangeQuery("outHospitalDate").lte(LocalDateUtil.getTimestamp(lastDayOfYear)));

        DateHistogramAggregationBuilder dateHistogramAgg = AggregationBuilders.dateHistogram("monthly_profit")
                .field("outHospitalDate")
                .calendarInterval(DateHistogramInterval.MONTH)
                .format("yyyy-MM")
                .timeZone(ZoneId.of("+08:00"))
                .subAggregation(AggregationBuilders.sum("fundCost").field("fundCost").format("0.00"));

        TermsAggregationBuilder groupAgg = AggregationBuilders.terms("group_aggs")
                .field("outDepartCode")
                .size(10)
                .subAggregation(AggregationBuilders.topHits("outDepartName").size(1)
                        .fetchSource(new String[]{"outDepartName"}, null))
                .subAggregation(dateHistogramAgg);


        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .addAggregation(groupAgg)
                .withPageable(PageRequest.of(0, 1))
                .build();

        Aggregations aggregations = elasticsearchOperations.search(searchQuery, PatientCaseEsPO.class).getAggregations();

        Terms groupTerms = aggregations.get("group_aggs");

        List<ChartLineSeriesVO> series = new ArrayList<>();

        for (Terms.Bucket entry : groupTerms.getBuckets()) {
            String departCodeCode = entry.getKeyAsString();

            TopHits topHits = entry.getAggregations().get("outDepartName");
            String groupName = EsResultResolveUtil.getName(topHits, 0, "outDepartName");

            Histogram perMonthAgg = entry.getAggregations().get("monthly_profit");
            Map<String, Object> dataMap = getMonthlyMap(perMonthAgg);
            List<Object> dataYList = Lists.newArrayList();
            for (String month : dataX) {
                Object value = dataMap.get(month);
                dataYList.add(ObjectUtils.isEmpty(value) ? null : value);
            }

            ChartLineSeriesVO seriesVO = new ChartLineSeriesVO();
            seriesVO.setSeriesName(groupName);
            seriesVO.setCode(departCodeCode);
            seriesVO.setDataList(dataYList);
            series.add(seriesVO);
        }

        ChartLineVO vo = new ChartLineVO();
        vo.setDataX(dataX);
        vo.setSeries(series);

        log.info("【EsDataMiningExtDAO.getExpireFundCostTren】 vo: {}", JSONObject.toJSONString(vo));
        return vo;
    }

    /**
     * 综合分析总(DSL-118)
     *
     * @param searchDepartCode
     * @param startDate
     * @param endDate
     */
    public List<ComprehensiveAnalysisPageVO> comprehensiveStt(String searchDepartCode, LocalDate startDate, LocalDate endDate) {
        // 检索条件
        BoolQueryBuilder queryBuilder = boolQuery();
        queryBuilder.must(QueryBuilders.termQuery("hasOut", true));
        if (StringUtils.isNotBlank(searchDepartCode)) {
            queryBuilder.must(QueryBuilders.termQuery("outDepartCode", searchDepartCode));
        }
        if (startDate != null) {
            queryBuilder.must(QueryBuilders.rangeQuery("settleDate").gte(LocalDateUtil.getTimestamp(startDate)));
        }
        if (endDate != null) {
            queryBuilder.must(QueryBuilders.rangeQuery("settleDate").lt(LocalDateUtil.getTimestamp(endDate.plusDays(1))));
        }

        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .addAggregation(AggregationBuilders.terms("doctorAgg")
                        .field("doctorCode")
                        .size(20000)
                        .order(BucketOrder.aggregation("total_profit", false))
                        .subAggregation(AggregationBuilders.sum("total_profit").field("profit").format("0.00"))
                        .subAggregation(AggregationBuilders.count("caseCount").field("caseCode"))
                        .subAggregation(AggregationBuilders.sum("totalCost").field("totalCost").format("0.00"))
                        .subAggregation(AggregationBuilders.sum("fundCost").field("fundCost").format("0.00"))
                        .subAggregation(AggregationBuilders.avg("avg_totalCost").field("totalCost").format("0.00"))
                        .subAggregation(AggregationBuilders.avg("avg_medicineCost").field("medicineCost").format("0.00"))
                        .subAggregation(AggregationBuilders.sum("medicineCost").field("medicineCost").format("0.00"))
                        .subAggregation(AggregationBuilders.sum("inpatientDays").field("inpatientDays"))
                        .subAggregation(AggregationBuilders.avg("avg_inpatientDays").field("inpatientDays").format("0.00"))
                        .subAggregation(AggregationBuilders.sum("inHospitalCost").field("inHospitalCost").format("0.00"))
                        .subAggregation(AggregationBuilders.cardinality("person_count").field("inpatientCode"))

                        .subAggregation(AggregationBuilders.topHits("groupName").size(2)
                                .fetchSource(new String[]{"departName", "doctorName"}, null))
                )
                .withPageable(PageRequest.of(0, 1))
                .build();

        Aggregations aggregations = elasticsearchOperations.search(searchQuery, PatientCaseEsPO.class).getAggregations();
        Terms doctorAgg = (ParsedStringTerms) aggregations.get("doctorAgg");
        List<ComprehensiveAnalysisPageVO> list = new ArrayList<>();
        for (Terms.Bucket bucket : doctorAgg.getBuckets()) {
            Aggregations agg = bucket.getAggregations();


            TopHits drgNameHits = (TopHits) bucket.getAggregations().get("groupName");
            //科室名称
            String departName = EsResultResolveUtil.getName(drgNameHits, 0, "departName");
            //医生名称
            String doctorName = EsResultResolveUtil.getName(drgNameHits, 0, "doctorName");

            //收入
            BigDecimal total_profit = EsResultResolveUtil.getSumValue(agg, "total_profit");
            //病例数
            Integer caseCount = EsResultResolveUtil.getValueCount(agg, "caseCount");
            //医疗总费用
            BigDecimal totalCost = EsResultResolveUtil.getSumValue(agg, "totalCost");
            //基金收入
            BigDecimal fundCost = EsResultResolveUtil.getSumValue(agg, "fundCost");
            //次均费用
            BigDecimal avg_totalCost = EsResultResolveUtil.getAvg(agg, "avg_totalCost");
            //次均药品费用
            BigDecimal avg_medicineCost = EsResultResolveUtil.getAvg(agg, "avg_medicineCost");
            //总药品费用
            BigDecimal medicineCost = EsResultResolveUtil.getSumValue(agg, "medicineCost");
            //总住院费用
            BigDecimal inHospitalCost = EsResultResolveUtil.getSumValue(agg, "inHospitalCost");
            //总住院天数
            Integer inpatientDays = EsResultResolveUtil.getSumIntValue(agg, "inHospitalCost");
            //平均入院日
            BigDecimal avg_inpatientDays = EsResultResolveUtil.getAvg(agg, "avg_inpatientDays");
            //患者数量
            Integer person_count = EsResultResolveUtil.getCardinalityValue(agg, "person_count");
            ComprehensiveAnalysisPageVO vo = new ComprehensiveAnalysisPageVO();
            vo.setDepartName(departName);
            vo.setDoctorName(doctorName);
            vo.setTotalProfit(total_profit);
            vo.setFundCost(fundCost);
            vo.setAvgTotalCost(avg_totalCost);
            vo.setAvgMedicineCost(avg_medicineCost);
            vo.setHospitalizationProfit(inHospitalCost);
            vo.setAverageDailyHospitalizationCost(inHospitalCost.divide(new BigDecimal(inpatientDays), 2, BigDecimal.ROUND_HALF_UP));
            vo.setAvgInpatientDays(avg_inpatientDays);
            vo.setPerPatientDischargedCost(totalCost.divide(new BigDecimal(person_count), 2, BigDecimal.ROUND_HALF_UP));
            vo.setInpatientDrugsProportion(BigDecimalUtil.formatBigDecimal(medicineCost.divide(totalCost, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)) + "%");
            list.add(vo);
        }
        return list;
    }

    /**
     * 超额排名分析(DSL-119)
     *
     * @param startDate
     * @param endDate
     */
    public List<OverRankingAnalysisPageVO> overRankStt(LocalDate startDate, LocalDate endDate) {

        // 检索条件
        BoolQueryBuilder queryBuilder = boolQuery();
        queryBuilder.must(QueryBuilders.termQuery("hasOut", true));
        if (startDate != null) {
            queryBuilder.must(QueryBuilders.rangeQuery("settleDate").gte(LocalDateUtil.getTimestamp(startDate)));
        }
        if (endDate != null) {
            queryBuilder.must(QueryBuilders.rangeQuery("settleDate").lt(LocalDateUtil.getTimestamp(endDate.plusDays(1))));
        }

        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .addAggregation(AggregationBuilders.terms("departAgg")
                        .field("outDepartCode")
                        .size(20000)
                        .subAggregation(AggregationBuilders.sum("controlStandard").field("controlStandard").format("0.00"))
                        .subAggregation(AggregationBuilders.sum("prePayTotal").field("prePayTotal").format("0.00"))
                        .subAggregation(AggregationBuilders.sum("caseBasedPayment").field("caseBasedPayment").format("0.00"))
                        .subAggregation(AggregationBuilders.sum("controlStandardDoctor").field("controlStandardDoctor").format("0.00"))
                        .subAggregation(AggregationBuilders.sum("prePayTotalDoctor").field("prePayTotalDoctor").format("0.00"))
                        .subAggregation(AggregationBuilders.sum("caseBasedPaymentDoctor").field("caseBasedPaymentDoctor").format("0.00"))


                        .subAggregation(AggregationBuilders.topHits("groupName").size(1)
                                .fetchSource(new String[]{"outDepartName",}, null))
                )
                .withPageable(PageRequest.of(0, 1))
                .build();

        Aggregations aggregations = elasticsearchOperations.search(searchQuery, PatientCaseEsPO.class).getAggregations();
        Terms departAgg = (ParsedStringTerms) aggregations.get("departAgg");
        List<OverRankingAnalysisPageVO> list = new ArrayList<>();
        for (Terms.Bucket bucket : departAgg.getBuckets()) {
            Aggregations agg = bucket.getAggregations();


            TopHits drgNameHits = (TopHits) bucket.getAggregations().get("groupName");
            //科室名称
            String departName = EsResultResolveUtil.getName(drgNameHits, 0, "outDepartName");

            //科室控制标准超额金额
            BigDecimal controlStandard = EsResultResolveUtil.getSumValue(agg, "controlStandard");
            //科室总额预付超额金额
            BigDecimal prePayTotal = EsResultResolveUtil.getSumValue(agg, "prePayTotal");
            //科室单病种付费超额金额
            BigDecimal caseBasedPayment = EsResultResolveUtil.getSumValue(agg, "caseBasedPayment");
            //医生控制标准超额金额
            BigDecimal controlStandardDoctor = EsResultResolveUtil.getSumValue(agg, "controlStandardDoctor");
            //医生总额预付超额金额
            BigDecimal prePayTotalDoctor = EsResultResolveUtil.getSumValue(agg, "prePayTotalDoctor");
            //医生单病种付费超额金额
            BigDecimal caseBasedPaymentDoctor = EsResultResolveUtil.getSumValue(agg, "caseBasedPaymentDoctor");
            OverRankingAnalysisPageVO vo = new OverRankingAnalysisPageVO();
            vo.setDepartName(departName);
            vo.setDepartmentMedicalInsuranceExcessCost(controlStandard);
            vo.setDepartmentMedicalInsurancePreExcessCost(prePayTotal);
            vo.setDepartmentMedicalInsuranceSingleDiseaseExcessCost(caseBasedPayment);
            vo.setDoctorMedicalInsuranceExcessCost(controlStandardDoctor);
            vo.setDoctorMedicalInsurancePreExcessCost(prePayTotalDoctor);
            vo.setDoctorMedicalInsuranceSingleDiseaseExcessCost(caseBasedPaymentDoctor);
            list.add(vo);
        }
        return list;
    }


    private Map<String, Object> getMonthlyMap(Histogram perMonthAgg) {
        Map<String, Object> map = Maps.newHashMap();
        List<? extends Histogram.Bucket> buckets = perMonthAgg.getBuckets();
        for (Histogram.Bucket bucket : buckets) {
            String month = bucket.getKeyAsString();
            ParsedSum sum = bucket.getAggregations().get("fundCost");
            BigDecimal totalProfit = BigDecimalUtil.parseBigDecimal(sum.getValueAsString());
            map.put(month, totalProfit);
        }
        return map;
    }

    private static BigDecimal randomRate(double min, double max) {
        return BigDecimal.valueOf(RandomUtil.randomDouble(min, max, 2, RoundingMode.HALF_UP));
    }
}
